package com.skyjing.askit.java.view;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.view.animation.LinearInterpolator;

import androidx.annotation.Nullable;

public class RhythmView extends View {

    private Paint linePaint;
    private int basePostion1;
    private int basePostion2;
    private int basePostion3;
    private int basePostion4;
    private int countRange;
    private int countPostion1;
    private int countPostion2;
    private int countPostion3;
    private int countPostion4;
    private int line1Width;
    private int line2Width;
    private int line3Width;
    private int line4Width;
    private int baseHeight;
    private ValueAnimator positiveAnim;
    private int duration = 500;
    private int lineColor = Color.parseColor("#954584");

    public RhythmView(Context context) {
        this(context, null);
    }

    public RhythmView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RhythmView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(attrs);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        final int minimumWidth = getSuggestedMinimumWidth();
        final int minimumHeight = getSuggestedMinimumHeight();
        int width;
        int height;
        width = measureWidth(minimumWidth, widthMeasureSpec);
        height = measureHeight(minimumHeight, heightMeasureSpec);
        setMeasuredDimension(width, height);
    }

    private int measureWidth(int defaultWidth, int measureSpec) {

        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);
        switch (specMode) {
            default:
            case MeasureSpec.AT_MOST:
                defaultWidth = dp2px(28) + getPaddingLeft() + getPaddingRight();
                break;
            case MeasureSpec.EXACTLY:
                defaultWidth = specSize;
                break;
            case MeasureSpec.UNSPECIFIED:
                defaultWidth = Math.max(defaultWidth, specSize);
        }
        return defaultWidth;
    }

    private int measureHeight(int defaultHeight, int measureSpec) {
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);
        switch (specMode) {
            default:
            case MeasureSpec.AT_MOST:
                defaultHeight = dp2px(40) + getPaddingTop() + getPaddingBottom();
                break;
            case MeasureSpec.EXACTLY:
                defaultHeight = specSize;
                break;
            case MeasureSpec.UNSPECIFIED:
                defaultHeight = Math.max(defaultHeight, specSize);
                break;
        }
        return defaultHeight;
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        line1Width = (int) (w * 0.20f);
        line2Width = (int) (w * 0.40f);
        line3Width = (int) (w * 0.60f);
        line4Width = (int) (w * 0.80f);
        baseHeight = (int) (h * 0.90f);
        basePostion1 = countPostion1 = (int) (h * 0.58f);
        basePostion2 = countPostion2 = (int) (h * 0.25f);
        basePostion3 = countPostion3 = (int) (h * 0.42f);
        basePostion4 = countPostion4 = (int) (h * 0.08f);
        countRange = (int) (h * 0.33f);
    }

    private void init(@Nullable AttributeSet attrs) {

        if (attrs != null) {
//            TypedArray array = this.getContext().obtainStyledAttributes(R.attr.rhy);
        }

        linePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        linePaint.setStrokeWidth(dp2px(5));
        linePaint.setStyle(Paint.Style.STROKE);
        linePaint.setColor(lineColor);
        //线头形状
        linePaint.setStrokeCap(Paint.Cap.ROUND);
        initAnim(0f, 1f);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawLine(line1Width, baseHeight, line1Width, countPostion1, linePaint);
        canvas.drawLine(line2Width, baseHeight, line2Width, countPostion2, linePaint);
        canvas.drawLine(line3Width, baseHeight, line3Width, countPostion3, linePaint);
        canvas.drawLine(line4Width, baseHeight, line4Width, countPostion4, linePaint);
    }

    public void start() {
        if (positiveAnim.isRunning()) {
            stop();
        }
        positiveAnim.start();
    }

    public void stop() {
        positiveAnim.cancel();
    }

    public void pause() {
        if (positiveAnim.isRunning()) {
            positiveAnim.pause();
        }

    }

    private void initAnim(final float from, final float to) {
        positiveAnim = ValueAnimator.ofFloat(from, to);
        positiveAnim.setDuration(duration);
        positiveAnim.setInterpolator(new LinearInterpolator());
        positiveAnim.setRepeatCount(-1);
        positiveAnim.setRepeatMode(ValueAnimator.REVERSE);

        positiveAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int current = (int) ((float) animation.getAnimatedValue() * countRange);
                if (countPostion1 != (basePostion1 - current)) {
                    countPostion1 = basePostion1 - current;
                    countPostion3 = basePostion3 - current;
                    countPostion2 = basePostion2 + current;
                    countPostion4 = basePostion4 + current;
                }
                postInvalidate();
            }
        });
    }

    private int dp2px(float dpVal) {
        return (int) TypedValue.applyDimension(1, dpVal, this.getResources().getDisplayMetrics());
    }

    public int getDuration() {
        return duration;
    }

    public RhythmView setDuration(int duration) {
        this.duration = duration;
        return this;
    }
}
